#include "Am2320.h"
#include "main.h"
#include "tool.h"

TM_AM2301_t AM2301_INT_Read(DRV_AM2301_Data_t* data) {
    volatile uint32_t time;
    uint8_t i, j, d[5];

    /* Set pin low for ~800-1000 us */
    AM2301_PIN_LOW;
    delay_us(1500);
    /* Set pin high to ~30 us */
    AM2301_PIN_HIGH;
    delay_us(30);

    tim_countUs_start();
    time = 0;
    /* Wait 20us for acknowledge, low signal */
    while (!AM2301_PIN_READ) {
        if (time > 85) {
            return TM_AM2301_CONNECTION_ERROR;
        }
        time = tim_countUs_get();
    }
    tim_countUs_stop();
    
    tim_countUs_start();
    time = 0;
    /* Wait 20us for acknowledge, low signal */
    while (AM2301_PIN_READ) {
        if (time > 85) {
            return TM_AM2301_CONNECTION_ERROR;
        }
        time = tim_countUs_get();
    }
    tim_countUs_stop();

    /* Read 5 bytes */
    for (j = 0; j < 5; j++) {
        d[j] = 0;
        for (i = 8; i > 0; i--) {
            tim_countUs_start();
            time = 0;
            /* Wait 20us for acknowledge, low signal */
            while (!AM2301_PIN_READ) {
                if (time > 85) {
                    return TM_AM2301_CONNECTION_ERROR;
                }
                time = tim_countUs_get();
            }
            tim_countUs_stop();

            tim_countUs_start();
            time = 0;
            /* Wait 20us for acknowledge, low signal */
            while (AM2301_PIN_READ) {
                if (time > 85) {
                    return TM_AM2301_CONNECTION_ERROR;
                }
                time = tim_countUs_get();
            }
            tim_countUs_stop();

            if (time > 22 && time < 30) {
                /* We read 0 */
            } else if(time > 68 && time < 85) {
                /* We read 1 */
              d[j] |= 1 << (i - 1);
            }
            else
            {
              return TM_AM2301_PARITY_ERROR;
            }
        }
    }

    /* Check for parity */
    if (((d[0] + d[1] + d[2] + d[3]) & 0xFF) != d[4]) {
        /* Parity error, data not valid */
        return TM_AM2301_PARITY_ERROR;
    }

    /* Set humidity */
    data->Hum = d[0] << 8 | d[1];
    /* Negative temperature */
    if (d[2] & 0x80) {
        data->Temp = -((d[2] & 0x7F) << 8 | d[3]);
    } else {
        data->Temp = (d[2]) << 8 | d[3];
    }

    /* Data OK */
    return TM_AM2301_OK;
}

